<?php
/**
 * 描述 : 核心数据操作的基础
 * 作者 : Edgar.lee
 */
class core_base {
    /**
     * 描述 : 当前事务错误信息
     * 结构 : {
     *          连接池名 : {
     *              "state" : 当前事务开启状态, true=开启, false=关闭
     *              "trans" : 事务执行结果 {
     *                  "state" : 是否成功, true=成功, false=失败
     *                  "data"  : 响应信息 [{
     *                      "state" : 单功能错误码
     *                      "info"  : 文本错误信息
     *                  }, ...]
     *              }
     *          }
     *      }
     * 作者 : Edgar.lee
     */
    private static $transInfo = array();

    /**
     * 描述 : 开启或关闭事务
     * 参数 :
     *      type : 默认=检查事务, null=开启事务, true=尝试提交事务, false=回滚事务
     *      pool : 数据连接池, "default"=默认
     * 返回 :
     *      开启或检查事务时 : 成功返回true, 失败返回false
     *      提交或回滚事务时 : 返回 {
     *          "state" : true=成功, false=失败
     *          "data"  : [{
     *              "state" : 单功能错误码
     *              "info"  : 文本错误信息
     *          }, ...]
     *      }
     * 作者 : Edgar.lee
     */
    public static function trans($type = 'state', $pool = 'default') {
        $trans = &self::$transInfo;

        //开启事务
        if ($type === null) {
            if ($trans) {
                trigger_error('已有未完成的事务开启');
                exit;
            } else {
                //清空错误日志
                of_base_error_writeLog::lastError(true);
                $type = L::sql(null, $pool);
                //初始化事务信息
                $trans[$pool] = array('state' => $type, 'data' => array());
                return $type;
            }
        //返回状态 type="state"
        } else if (is_string($type)) {
            return !empty($trans[$pool]['state']);
        //操作事务
        } else if (isset($trans[$pool])) {
            $info = &$trans[$pool];

            //提交或回滚
            if (is_bool($type)) {
                //发生错误
                if (of_base_error_writeLog::lastError()) {
                    $info['state'] = false;
                    $info['data'][] = '发生未知错误';
                }

                //提交事务
                if ($type && $info['state']) {
                    //提交失败
                    ($info['state'] = L::sql(true, $pool)) || $info['data'][] = '事务提交失败';
                //回滚事务
                } else {
                    $info['state'] = false;
                    L::sql(false, $pool);
                }

                $trans = array();
                return $info;
            //设置事务信息, 数组 && 是错误信息
            } else if ($type['state'] !== 200) {
                $info['state'] = false;
                $info['data'][] = &$type['info'];
            }
        } else {
            trigger_error('没有开启事务');
            exit;
        }
    }

    /**
     * 描述 : 获取当前登录帐号
     * 返回 :
     *      返回登录的帐号,未登录返回""
     * 作者 : Edgar.lee
     */
    public static function getUser($slashes = false) {
        $temp = (string)of_base_sso_tool::user('name');
        return $slashes ? addslashes($temp) : $temp;
    }

    /**
     * 描述 : 同步回调封装
     * 参数 :
     *      callkey : 回调名称 /config/core_base/callBack.php 键
     *      params  : 触发参数
     * 返回 :
     *      
     * 作者 : Edgar.lee
     */
    public static function callFunc($call, $params = null) {
        $config = include ROOT_DIR . '/config/core_base/callBack.php';

        if (isset($config[$call])) {
            return of::callFunc($config[$call], $params);
        } else {
            return true;
        }
    }

    /**
     * 描述 : 返回基础配置
     * 参数 :
     *      $key : 指定返回配置
     * 作者 : zzg
     */
    public static function baseConfig($key = null) {
        $config = include ROOT_DIR . '/config/core_base/base.php';
        if ($key === null) {
            return $config;
        } else if (isset($config[$key])) {
            return $config[$key];
        } else {
            return false;
        }
    }

    /**
     * 描述 : 日志表
     * 参数 ：
     *      msg  日志信息
     *      name 日志文件夹
     *      timeAppend 是否默认时间 默认true
     *      hour 是否分小时保存一个文件 默认false
     * 作者 : Smart.Chen
     */
    public static function log($msg, $name = 'hyjk', $timeAppend = true, $hour = false, $id = '') {
        //文件夹是否存在
        if (!is_dir(ROOT_DIR . '/data/log/' . $name)) {
            mkdir(ROOT_DIR . '/data/log/' . $name, 0777, true);
        }
        if ($hour) {
            $path = ROOT_DIR . '/data/log/' . $name . '/' . date('Y-m-d_H') . $id . '.log';
        } else {
            $path = ROOT_DIR . '/data/log/' . $name . '/' . date('Y-m-d') . $id . '.log';
        }
        if (file_exists($path)) {
            $myfile = fopen($path, "a");//存在则打开
        } else {
            $myfile = fopen($path, "w");//创建
        }
        if (is_array($msg)) {
            $msg = json_encode($msg, JSON_UNESCAPED_UNICODE);
        }
        if ($timeAppend) {
            $msg = date('Y-m-d H:i:s') . ': ' . $msg . "\n";
        }
        fwrite($myfile, $msg);
        fclose($myfile);
        //删除日志文件
        self::delFile(ROOT_DIR . '/data/log/' . $name, 30, 'log');
    }


    /**
     * 描述 : 删除指定目录指定类型N天前的文件
     * 参数 : $dir 目录路径 $n 天数（默认删除7天前的） $type 文件类型（默认zip）
     * 作者 : Smart.Chen
     */
    public static function delFile($dir, $n = 7, $type = 'zip') {
        $key = md5($dir.$type);
        if (of_base_com_kv::get($key)) {
            return true;
        }
        of_base_com_kv::set($key, time());
        //        //这是删除目录下的文件及文件夹  先删除目录下的文件：
        //        $dh = @opendir($dir);
        //        while ($file = @readdir($dh)) {
        //            if($file!="." && $file!="..") {
        //                $fullpath=$dir."/".$file;
        //                if(!is_dir($fullpath)) {
        //                    @unlink($fullpath);
        //                } else {
        //                    self::deldir($fullpath);
        //                }
        //            }
        //        }
        //        @closedir($dh);
        //        @rmdir($dir);
        //        //删除当前文件夹：
        //        if(rmdir($dir)) {
        //            return true;
        //        } else {
        //            return false;
        //        }
        if (is_dir($dir)) {
            if ($dh = opendir($dir)) {
                while (false !== ($file = readdir($dh))) {
                    if ($file != "." && $file != "..") {
                        $fullpath = $dir . "/" . $file;
                        if (!is_dir($fullpath)) {
                            $extension = pathinfo($fullpath, PATHINFO_EXTENSION);//获取文件后缀
                            $filedate = date("Y-m-d", filemtime($fullpath));
                            $d1 = strtotime(date("Y-m-d"));
                            $d2 = strtotime($filedate);
                            $Days = round(($d1 - $d2) / 3600 / 24);
                            if ($extension == $type && $Days > $n) {
                                unlink($fullpath);  ////删除文件
                            }
                        }
                    }
                }
            }
            closedir($dh);
        }
    }

    /**
     * 描述 : curl请求
     * 作者 : Zoro.Zhu
     */
    public static function curl($url, $data=null, $method='get', $header = array("content-type: application/json"), $https=true, $timeout = 30){
        $method = strtoupper($method);
        $ch = curl_init();//初始化
        curl_setopt($ch, CURLOPT_URL, $url);//访问的URL
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//只获取页面内容，但不输出
        if($https){
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//https请求 不验证证书
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//https请求 不验证HOST
        }
        if ($method != "GET") {
            if($method == 'POST'){
                curl_setopt($ch, CURLOPT_POST, true);//请求方式为post请求
            }
            if ($method == 'PUT' || strtoupper($method) == 'DELETE') {
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //设置请求方式
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//请求数据
        }
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //模拟的header头
        //curl_setopt($ch, CURLOPT_HEADER, false);//设置不需要头信息
        $result = curl_exec($ch);//执行请求
        curl_close($ch);//关闭curl，释放资源
        return $result;
    }

    /**
     * 描述 : 日志表
     * 参数 ：
     *      msg  日志信息
     *      name 日志文件夹
     * 作者 : Smart.Chen
     */
    public static function pdf($str, $name = 'hyjk') {
        $path = ROOT_DIR . '/data/pdf/' . $name . '.pdf';
        if (file_exists($path)) {
            $myfile = fopen($path, "a");//存在则打开
        } else {
            $myfile = fopen($path, "w");//创建
        }
        fwrite($myfile, $str);
        fclose($myfile);
        return ROOT_URL . '/data/pdf/' . $name . '.pdf';
    }

    /**
     * 描述 : 获取响应头
     * 作者 : Zoro.Zhu
     */
    public static function posttoken($url,$data,$headers=[]) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        // 返回 response_header, 该选项非常重要,如果不为 true, 只会获得响应的正文
        curl_setopt($curl, CURLOPT_HEADER, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        // TRUE 将curl_exec()获取的信息以字符串返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POST, 1);
        // 是否不需要响应的正文,为了节省带宽及时间,在只需要响应头的情况下可以不要正文
        // curl_setopt($curl, CURLOPT_NOBODY, true);
        // 设置post数据
        $post_data = $data;
        curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
        $data = curl_exec($curl);
        // 获得响应结果里的：头大小
        $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        // 根据头大小去获取头信息内容
        $header = substr($data, 0, $headerSize);
        curl_close($curl);
        return $header;
    }
}
